package live.zs.securitystarter.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.sql.DataSource;

/**
 * @author madison
 * @description
 * @date 2021/7/15 20:07
 */
//加入spring-boot-starter-security依赖就会自动启用
//@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin(
                form -> form.loginPage("/loginPage")        //用户未登录时，访问任何资源都转跳到该路径，即登录页面（自定义的话要加上antMatchers("/loginPage").permitAll()）
                        .loginProcessingUrl("/formLogin")   //登录表单form中action的地址，也就是处理认证请求的路径, 默认/login
                        // .usernameParameter("uname")      //登录表单form中用户名输入框input的name名，不修改的话默认是username
                        // .passwordParameter("pword")      //form中密码输入框input的name名，不修改的话默认是password
                        .defaultSuccessUrl("/index")        //登录认证成功后默认转跳的路径
                        // .failureUrl("/login-error")
        ).logout(
                logout -> logout.logoutUrl("/logouttttt")       // 默认/logout  注意: 如果启用了 CSRF 保护（默认），则请求也必须是 POST
                        .logoutSuccessUrl("/loginPage?logout")  // 默认/login?logout
        ).authorizeRequests(
                auth -> auth.antMatchers("/loginPage", "/actuator/**")
                        .permitAll()
                        .anyRequest()
                        .authenticated()
        ).httpBasic(Customizer.withDefaults()               // 请求头 Authorization: Basic bWFkaXNvbjp6czEwMTI= (明文为madison:zs1012)
        );
//                .csrf(csrf -> csrf.disable())      //CSRF - Cross-Site Request Forgery - 跨站请求伪造
//                .cors(cors -> cors.disable());     //CORS - Cross Origin Resource-Sharing - 跨站资源共享

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

        UserDetails user = User.withDefaultPasswordEncoder()
                .username("madison")
                .password("zs1012")
                .roles("ROLES")
                .build();

        auth
                .inMemoryAuthentication()
                .withUser("madison1")
                .password("{bcrypt}$2a$10$OUINml/M7qm9S8OXO.xMxe4Y/IiLA4uUg6f4WNErJ04PamjLz/hHi") // spring encodepassword zs1012
                .roles("ROLES")

                .and()
                .withUser("madison2")
                .password("{noop}zs1012") // 可以选择在密码前加上前缀{noop}以指示不应使用编码。
                .roles("ROLES")

                .and()
                .withUser("madison3")
                .password(passwordEncoder.encode("zs1012"))
                .roles("ROLES")

                .and()
                .withUser(user)

                // 默认JDBC实现 madison4 zs111
                .and()
                .jdbcAuthentication()
                .dataSource(dataSource)
//                .withDefaultSchema()
//                .and()
//                .userDetailsService(new JdbcDaoImpl())

                // 自定义JDBC
                .and()
                .userDetailsService(customUserDetailsService())
                .passwordEncoder(new BCryptPasswordEncoder())
        ;
    }

    @Bean
    CustomUserDetailsService customUserDetailsService() {
        return new CustomUserDetailsService();
    }

//    @Bean
//    UserDetailsManager userDetailsManager() {
//        UserDetails user = User.builder()
//                .username("madison4")
//                .password("{bcrypt}$2a$10$ZyavNSzSWpIPi53/gQf8o.7RT3F7G2wxaYxXbPvmaTT4ZBJo.ZVoC") //zs111
//                .roles("USER")
//                .build();
//        JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
//        users.createUser(user);
//        return users;
//    }
}
